package life.majiang.community.service;

import life.majiang.community.dto.CommentDTO;
import life.majiang.community.dto.CommentLikeCountDTO;
import life.majiang.community.dto.PaginationDTO;
import life.majiang.community.enums.CommentTypeEnum;
import life.majiang.community.enums.NotificationStatusEnum;
import life.majiang.community.enums.NotificationTypeEnum;
import life.majiang.community.exception.CustomizeErrorCode;
import life.majiang.community.exception.CustomizeException;
import life.majiang.community.mapper.*;
import life.majiang.community.model.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by codedrinker on 2019/5/31.
 */
@Service
public class CommentService {

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionExtMapper questionExtMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CommentExtMapper commentExtMapper;

    @Autowired
    private NotificationMapper notificationMapper;

    @Autowired
    private LikeCountMapper likeCountMapper;

    @Transactional
    public void insert(Comment comment, User commentator) {
        if (comment.getParentId() == null || comment.getParentId() == 0) {
            throw new CustomizeException(CustomizeErrorCode.TARGET_PARAM_NOT_FOUND);
        }
        if (comment.getType() == null || !CommentTypeEnum.isExist(comment.getType())) {
            throw new CustomizeException(CustomizeErrorCode.TYPE_PARAM_WRONG);
        }
        if (comment.getType() == CommentTypeEnum.COMMENT.getType()) {
            // 回复评论
            Comment dbComment = commentMapper.selectByPrimaryKey(comment.getParentId());
            if (dbComment == null) {
                throw new CustomizeException(CustomizeErrorCode.COMMENT_NOT_FOUND);
            }

            // 回复问题
            Question question = questionMapper.selectByPrimaryKey(dbComment.getParentId());
            if (question == null) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }

            commentMapper.insert(comment);

            // 增加评论数
            Comment parentComment = new Comment();
            parentComment.setId(comment.getParentId());
            parentComment.setCommentCount(1);
            commentExtMapper.incCommentCount(parentComment);

            // 创建通知
            createNotify(comment, dbComment.getCommentator(), commentator.getName(), question.getTitle(), NotificationTypeEnum.REPLY_COMMENT, question.getId());
        } else {
            // 回复问题
            Question question = questionMapper.selectByPrimaryKey(comment.getParentId());
            if (question == null) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
            comment.setCommentCount(0);
            commentMapper.insert(comment);
            question.setCommentCount(1);
            questionExtMapper.incCommentCount(question);

            // 创建通知
            createNotify(comment, question.getCreator(), commentator.getName(), question.getTitle(), NotificationTypeEnum.REPLY_QUESTION, question.getId());
        }
    }

    private void createNotify(Comment comment, Long receiver, String notifierName, String outerTitle, NotificationTypeEnum notificationType, Long outerId) {
        if (receiver == comment.getCommentator()) {
            return;
        }
        Notification notification = new Notification();
        notification.setGmtCreate(System.currentTimeMillis());
        notification.setType(notificationType.getType());
        notification.setOuterid(outerId);
        notification.setNotifier(comment.getCommentator());
        notification.setStatus(NotificationStatusEnum.UNREAD.getStatus());
        notification.setReceiver(receiver);
        notification.setNotifierName(notifierName);
        notification.setOuterTitle(outerTitle);
        notificationMapper.insert(notification);
    }

    public List<CommentDTO> listByTargetId(Long id, CommentTypeEnum type) {
        CommentExample commentExample = new CommentExample();
        commentExample.createCriteria()
                .andParentIdEqualTo(id)
                .andTypeEqualTo(type.getType());
        commentExample.setOrderByClause("gmt_create asc");
        List<Comment> comments = commentMapper.selectByExample(commentExample);

//        for(Comment com :comments){
//            System.out.println(com.getAnonymous());
//        }

        if (comments.size() == 0) {
            return new ArrayList<>();
        }
        // 获取去重的评论人
        Set<Long> commentators = comments.stream().map(comment -> comment.getCommentator()).collect(Collectors.toSet());
        List<Long> userIds = new ArrayList();
        userIds.addAll(commentators);


        // 获取评论人并转换为 Map
        UserExample userExample = new UserExample();
        userExample.createCriteria()
                .andIdIn(userIds);
        List<User> users = userMapper.selectByExample(userExample);
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(user -> user.getId(), user -> user));


        // 转换 comment 为 commentDTO
        List<CommentDTO> commentDTOS = comments.stream().map(comment -> {
            CommentDTO commentDTO = new CommentDTO();
            BeanUtils.copyProperties(comment, commentDTO);
            commentDTO.setUser(userMap.get(comment.getCommentator()));
            return commentDTO;
        }).collect(Collectors.toList());

        return commentDTOS;
    }

//    新增点赞功能
    @Transactional
    public void updateLikeCount(Comment comment, CommentLikeCountDTO commentLikeCount){
        boolean isUpdate = commentMapper.updateLikeCount(comment);
        boolean isAddOrRemove;

        if(commentLikeCount.getType().equals("yes")){
//            点赞
            isAddOrRemove = likeCountMapper.insertLikeCount(commentLikeCount);
        }else{
//            取消赞
            isAddOrRemove = likeCountMapper.removeLikeCount(commentLikeCount);
        }

//        没有成功回滚
        if(!(isAddOrRemove && isUpdate)){
            throw new RuntimeException();
        }
    }

//    根据id批量删除评论
    public boolean removeCommentByIds(List<Comment> comments){
        return commentMapper.removeCommentByIds(comments);
    }

    public List<Comment> getCommentsByQuestionId(Long questionId){
        return commentMapper.getCommentsByQuestionId(questionId);
    }

    List<Comment> getCommentsByIdAndTypeEQ2(List<Comment> comments){
        return commentMapper.getCommentsByIdAndTypeEQ2(comments);
    }

    public PaginationDTO<CommentSTD> getAllCommentByPagination(String search, Integer page, Integer size){
        PaginationDTO<CommentSTD> commentSTDPaginationDTO = new PaginationDTO<>();

        Integer totalPage = 0;

        Integer totalCount = commentMapper.getCommentCountByTypeEQ1(search);

        if (totalCount % size == 0) {
            totalPage = totalCount / size;
        } else {
            totalPage = totalCount / size + 1;
        }

        if (page > totalPage) {
            page = totalPage;
        }

        if (page < 1) {
            page = 1;
        }

        commentSTDPaginationDTO.setPagination(totalPage, page);

        List<CommentSTD> commentSTDS = commentMapper.getAllCommentByPagination(commentSTDPaginationDTO, search, (page - 1) * size, size);
        commentSTDPaginationDTO.setData(commentSTDS);
        return commentSTDPaginationDTO;
    }

//    根据id删除评论
    public boolean removeCommentByIdAndTypeEQ2(Long id){
        int flag = commentMapper.deleteByPrimaryKey(id);
        return flag > 0;
    }

    @Transactional
    public void removeSecodeCommentByIdAndUpdateCommentCount(Long id, Long parentId){
        boolean removeSecodeComment = removeCommentByIdAndTypeEQ2(id);

        Comment parentComment = commentMapper.selectByPrimaryKey(parentId);

        boolean updateCommentCount = commentMapper.updateCommentCount(parentId, parentComment.getCommentCount() - 1);

        if(!(removeSecodeComment && updateCommentCount)){
            throw new CustomizeException(CustomizeErrorCode.INVALID_INPUT);
        }
    }

//    根据id删除一级评论和点赞
    @Transactional
    public boolean removeCommentByIdAndTypeEQ1(Long id, Long likeCount, Integer commentCount, Long parentId){
        boolean isDeleteLikeCount = true;
        boolean isDeleteSecondComment = true;
        if(likeCount != 0){
            isDeleteLikeCount = likeCountMapper.removeLikeCountByCommentId(id);
        }
//        删除下面的二级评论

        if(commentCount != 0){
            isDeleteSecondComment = commentMapper.removeCommentByParentId(id);
        }

        boolean isDeleteComment = removeCommentByIdAndTypeEQ2(id);

        Question question = questionMapper.selectByPrimaryKey(parentId);

        boolean isUpdateQuestionCommentCount = questionMapper.updateQuestionCommentCountById(parentId, question.getCommentCount() - 1);

        if(!(isDeleteComment && isDeleteLikeCount && isDeleteSecondComment && isUpdateQuestionCommentCount)){
            throw new CustomizeException(CustomizeErrorCode.INVALID_INPUT);
        }

        return isDeleteComment && isDeleteLikeCount && isDeleteSecondComment;
    }
}
